
// import * as d3 from "../lib/d3.js";
import * as d3 from "d3";
import {isEnabled, isInert} from "./util.js";
import {findIndex, findLastIndex} from "underscore";

/**
 * @param {HTMLElement} node
 * @returns {boolean} true if the node is currently interactable, otherwise false
 */
export function isClickable(node) {
    return isEnabled(node) && !isInert(node);
}

/**
 * @param {HTMLElement[]} nodes
 * @returns {HTMLElement} the first element in the array that is clickable, or undefined if none
 */
export function firstClickable(nodes) {
    return nodes[findIndex(nodes, isClickable)];
}

/**
 * @param {HTMLElement[]} nodes
 * @param {number} start
 * @param {number} step
 * @returns {HTMLElement} the next element in the array that is clickable, or undefined if none
 */
export function nextClickable(nodes, start, step) {
    const n = nodes.length;
    for (let next = start + step; 0 <= next && next < n; next += step) {
        if (isClickable(nodes[next])) {
            return nodes[next];
        }
    }
}

/**
 * @param {HTMLElement[]} nodes
 * @returns {HTMLElement} the last element in the array that is clickable, or undefined if none
 */
export function lastClickable(nodes) {
    return nodes[findLastIndex(nodes, isClickable)];
}

/**
 * @returns {MouseEvent} a new mouse click event instance
 */
function newClickEvent() {
    try {
        return new MouseEvent("click", {view: window, bubbles: true, cancelable: true});
    } catch(e) {
        // Chrome mobile supports only the old fashioned, deprecated way of constructing events. :(
        const event = document.createEvent("MouseEvents");
        event.initMouseEvent("click", true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
        return event;
    }
}

/**
 * Triggers a click event on the specified node.
 *
 * @param {HTMLElement|string} node a DOM node or a D3 selector string for a DOM node
 * @returns {boolean} true when the node is clickable and a click event was dispatched
 */
export function clickOn(node) {
    if (typeof node === "string") {
        node = d3.select(node).node();
    }
    if (isClickable(node)) {
        node.dispatchEvent(newClickEvent());
        return true;
    }
    return false;
}
